﻿// Sequin.Sequences.IO.SequenceWriter
//
// (c) 2011 Arthur Pitman
//
// Part of the Sequin Library
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License (Version 2.1) as published by the Free Software Foundation.
// 
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public
// License (Version 2.1) along with this library; if not, write to the 
// Free Software Foundation, Inc., 
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
// or see <http://www.gnu.org/licenses/>.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Compression;

namespace Sequin.Sequences.IO
{
	/// <summary>
	/// Writes sequences to a file
	/// </summary>
	public class SequenceWriter : ISequenceWriter
	{
		/// <summary>
		/// The <see cref="StreamWriter"/> associated with the <see cref="SequenceWriter"/>
		/// </summary>
		protected StreamWriter writer = null;

		/// <summary>
		/// The <see cref="ISymbolMapper"/> associated with the <see cref="SequenceWriter"/> 
		/// </summary>
		protected ISymbolMapper symbolMapper = null;

		/// <summary>
		/// The <see cref="ISequenceFormatter"/> associated with the <see cref="SequenceWriter"/> 
		/// </summary>
		protected ISequenceFormatter sequenceFormatter = null;

		/// <summary>
		/// Writes a series of <see cref="Sequence"/> objects to a file
		/// </summary>
		/// <param name="sequences">The <see cref="Sequence"/> objects to write</param>
		/// <param name="symbolMapper">The <see cref="ISymbolMapper"/> to use</param>
		/// <param name="filename">The filename to create and write to</param>
		/// <param name="compressed">Indicates if the file is compressed</param>
		public static void WriteSequencesToFile(IEnumerable<Sequence> sequences, ISymbolMapper symbolMapper, string filename, bool compressed)
		{
			StreamWriter streamWriter = null;
			if (compressed)
				streamWriter = new StreamWriter(new GZipStream(new FileStream(filename, FileMode.Create), CompressionMode.Compress));
			else
				streamWriter = File.CreateText(filename);
			var sw = new SequenceWriter(streamWriter, symbolMapper);
			foreach (var sequence in sequences)
				sw.WriteSequence(sequence);
			sw.Close();
		}

		/// <summary>
		/// Initializes a new <see cref="SequenceWriter"/> instance
		/// </summary>
		/// <param name="writer">The <see cref="StreamWriter"/> to use</param>
		/// <param name="symbolMapper">The <see cref="ISymbolMapper"/> to use</param>
		public SequenceWriter(StreamWriter writer, ISymbolMapper symbolMapper) : this(writer, symbolMapper, new SequenceFormatter())
		{		
		}

		/// <summary>
		/// Initializes a new <see cref="SequenceWriter"/> instance
		/// </summary>
		/// <param name="writer">The <see cref="StreamWriter"/> to use</param>
		/// <param name="symbolMapper">The <see cref="ISymbolMapper"/> to use</param>
		/// <param name="sequenceFormatter">The <see cref="ISequenceFormatter"/> to use</param>
		public SequenceWriter(StreamWriter writer, ISymbolMapper symbolMapper, ISequenceFormatter sequenceFormatter)
		{
			this.writer = writer;
			this.symbolMapper = symbolMapper;
			this.sequenceFormatter = sequenceFormatter;
		}

		/// <summary>
		/// Writes a <see cref="Sequence"/>
		/// </summary>
		/// <param name="sequence">The <see cref="Sequence"/> to write</param>
		public void WriteSequence(Sequence sequence)
		{
			writer.WriteLine(sequenceFormatter.SequenceToString(sequence, symbolMapper));
		}

		/// <summary>
		/// Closes the <see cref="StreamWriter"/> associated with this <see cref="SequenceWriter"/>
		/// </summary>
		public void Close()
		{
			if (writer != null)
			{
				writer.Close();
				writer = null;
			}
		}     
	}
}
